package cvo.chess.tests.pieces;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.List;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import cvo.chess.client.entities.IGameFacade;
import cvo.chess.client.entities.armies.pieces.Rook;
import cvo.chess.client.entities.chessboard.ChessboardCoordinate;
import cvo.chess.client.entities.chessboard.IChessboardCoordinate;
import cvo.chess.client.entities.chessboard.ITile;
import cvo.chess.client.entities.game.Army;
import cvo.chess.client.entities.game.Chessboard;
import cvo.chess.client.entities.game.IPiece;

public class RookTestPossibleMoves {
	private IGameFacade gf;
	private ITile tile;
	private Chessboard board;
	private IChessboardCoordinate chessco;
	private Army army;
	
	@Before
	public void setUp(){
		gf = mock(IGameFacade.class);
		tile = mock(ITile.class);
		when(tile.getPosition()).thenReturn("A1");
		when(gf.getTileAt("A1")).thenReturn(tile);
		
		army = mock(Army.class);
		when(army.getColor()).thenReturn("WHITE");
		
		
		board = mock(Chessboard.class);
		when(board.getHeight()).thenReturn(8);
		when(board.getWidth()).thenReturn(8);
		
		chessco = mock(IChessboardCoordinate.class);
		
	}
	
	@Test
	public void testMockito(){
		ITile t = gf.getTileAt("A1");
		Assert.assertEquals("Postion must be A1", "A1", t.getPosition());

	}
	
	@Test
	public void testWhenRookOnE5() throws Exception{
		IPiece rook = new Rook(gf, army);	
		
		chessco.setA1Notation("E5");
		when(chessco.getRow()).thenReturn(4);
		when(chessco.getCol()).thenReturn(3);
		when(chessco.getA1Notation()).thenReturn("E5");
		when(gf.getPositionOfPiece(rook)).thenReturn(chessco);	
		
		gf.setPieceAtPosition(rook, chessco);
		
		Assert.assertNotNull("List of possible moves may not be null", rook.getPossibleMoves());
		
		Assert.assertFalse("List must contain more possible moves", rook.getPossibleMoves().isEmpty());
		
		List<ChessboardCoordinate> list = rook.getPossibleMoves();
		
		Assert.assertTrue("Does not contain E8", list.contains(new ChessboardCoordinate(board, "E8")));
		Assert.assertTrue("Does not contain E7", list.contains(new ChessboardCoordinate(board, "E7")));
		Assert.assertTrue("Does not contain E6", list.contains(new ChessboardCoordinate(board, "E6")));
		Assert.assertTrue("Does not contain E4", list.contains(new ChessboardCoordinate(board, "E4")));
		Assert.assertTrue("Does not contain E1", list.contains(new ChessboardCoordinate(board, "E1")));

		
		Assert.assertTrue("Does not contain A5", list.contains(new ChessboardCoordinate(board, "A5")));
		Assert.assertTrue("Does not contain B5", list.contains(new ChessboardCoordinate(board, "B5")));
		Assert.assertTrue("Does not contain C5", list.contains(new ChessboardCoordinate(board, "C5")));
		Assert.assertTrue("Does not contain D5", list.contains(new ChessboardCoordinate(board, "D5")));
		Assert.assertTrue("Does not contain F5", list.contains(new ChessboardCoordinate(board, "F5")));
		Assert.assertTrue("Does not contain G5", list.contains(new ChessboardCoordinate(board, "G5")));
		Assert.assertTrue("Does not contain H5", list.contains(new ChessboardCoordinate(board, "H5")));
		
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"E5")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A1")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"H1")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A8")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"H8")));
		
		
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A3")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"C7")));
	}
	
	@Test
	public void testWhenRookOnA1() throws Exception{
		IPiece rook = new Rook(gf, army);	
		
		chessco.setA1Notation("A1");
		when(chessco.getRow()).thenReturn(0);
		when(chessco.getCol()).thenReturn(7);
		when(chessco.getA1Notation()).thenReturn("A1");
		when(gf.getPositionOfPiece(rook)).thenReturn(chessco);	
		
		gf.setPieceAtPosition(rook, "A1");	
		
		Assert.assertNotNull("List of possible moves may not be null", rook.getPossibleMoves());
		
		Assert.assertFalse("List must contain more possible moves", rook.getPossibleMoves().isEmpty());
		
		List<ChessboardCoordinate> list = rook.getPossibleMoves();
		
		// Fields that should be in the list of possible moves
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A2")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A3")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A7")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A5")));

		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "B1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "C1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "D1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "E1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "F1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "G1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H1")));
		
		// proximate fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B2")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B3")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"C2")));
		
		// opposite corner should not be in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"H8")));
		
		// random fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A3")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"C7")));
		
		// check that current Position of the piece is not in the list!
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A1")));
	}
	
	@Test
	public void testWhenRookOnA8() throws Exception{
		IPiece rook = new Rook(gf, army);		
		
		chessco.setA1Notation("A8");
		when(chessco.getRow()).thenReturn(0);
		when(chessco.getCol()).thenReturn(0);
		when(chessco.getA1Notation()).thenReturn("A8");
		when(gf.getPositionOfPiece(rook)).thenReturn(chessco);	
		
		gf.setPieceAtPosition(rook, "A8");	
		
		Assert.assertNotNull("List of possible moves may not be null", rook.getPossibleMoves());
		
		Assert.assertFalse("List must contain more possible moves", rook.getPossibleMoves().isEmpty());
		
		List<ChessboardCoordinate> list = rook.getPossibleMoves();
		
		// Fields that should be in the list of possible moves
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A2")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A3")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A7")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A5")));

		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "B8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "C8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "D8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "E8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "F8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "G8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H8")));
		
		// proximate fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B7")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"C7")));
		
		// opposite corner should not be in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"H1")));
		
		// random fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A3")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"C7")));
		
		// check that current Position of the piece is not in the list!
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A8")));
	}
	
	@Test
	public void testWhenRookOnH1() throws Exception{
		IPiece rook = new Rook(gf, army);		
		
		chessco.setA1Notation("H1");
		when(chessco.getRow()).thenReturn(7);
		when(chessco.getCol()).thenReturn(7);
		when(chessco.getA1Notation()).thenReturn("H1");
		when(gf.getPositionOfPiece(rook)).thenReturn(chessco);	
		
		gf.setPieceAtPosition(rook, "H1");	
		
		Assert.assertNotNull("List of possible moves may not be null", rook.getPossibleMoves());
		
		Assert.assertFalse("List must contain more possible moves", rook.getPossibleMoves().isEmpty());
		
		List<ChessboardCoordinate> list = rook.getPossibleMoves();
		
		// Fields that should be in the list of possible moves
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H2")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H3")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H7")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H5")));

		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "B1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "C1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "D1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "E1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "F1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "G1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A1")));
		
		// proximate fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B2")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B3")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"C2")));
		
		// opposite corner should not be in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A8")));
		
		// random fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A3")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"C7")));
		
		// check that current Position of the piece is not in the list!
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"H1")));
	}
	
	@Test
	public void testWhenRookOnH8() throws Exception{
		IPiece rook = new Rook(gf, army);		
		
		chessco.setA1Notation("H8");
		when(chessco.getRow()).thenReturn(7);
		when(chessco.getCol()).thenReturn(0);
		when(chessco.getA1Notation()).thenReturn("H8");
		when(gf.getPositionOfPiece(rook)).thenReturn(chessco);	
		
		gf.setPieceAtPosition(rook, "H8");	
		
		Assert.assertNotNull("List of possible moves may not be null", rook.getPossibleMoves());
		
		Assert.assertFalse("List must contain more possible moves", rook.getPossibleMoves().isEmpty());
		
		List<ChessboardCoordinate> list = rook.getPossibleMoves();
		
		// Fields that should be in the list of possible moves
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H2")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H3")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H7")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "H5")));

		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "B8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "C8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "D8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "E8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "F8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "G8")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A8")));
		
		// proximate fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B7")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"C7")));
		
		// opposite corner should not be in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A1")));
		
		// random fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A3")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"C7")));
		
		// check that current Position of the piece is not in the list!
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"H8")));
	}
	
	@Test
	public void testWhenRookOnD6PlusPiece() throws Exception{
		IPiece rook = new Rook(gf, army);	
		
		chessco.setA1Notation("D6");
		when(chessco.getRow()).thenReturn(3);
		when(chessco.getCol()).thenReturn(2);
		when(chessco.getA1Notation()).thenReturn("D6");
		when(gf.getPositionOfPiece(rook)).thenReturn(chessco);	
		
		gf.setPieceAtPosition(rook, "D6");
		
		//put a piece on the board. we assume it is of the same army!
		IPiece pawn = mock(IPiece.class);
		//mock object is beter te gebruiken!!
		gf.setPieceAtPosition(pawn, "F6");
		when(gf.getPieceAt("F6")).thenReturn(pawn);
		when(pawn.getColor()).thenReturn("Wit");
		
		Assert.assertNotNull("List of possible moves may not be null", rook.getPossibleMoves());
		
		Assert.assertFalse("List must contain more possible moves", rook.getPossibleMoves().isEmpty());
		
		List<ChessboardCoordinate> list = rook.getPossibleMoves();
		
		// Fields that should be in the list of possible moves
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "D2")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "D3")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "D1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "D7")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "D5")));

		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A6")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "B6")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "C6")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "E6")));
		
		// proximate fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B7")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"C7")));
		
		// fields from the other piece on, should not be in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"G6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"H6")));
		
		// random fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A2")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B1")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F8")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A5")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"G7")));
		
		// check that current Position of the piece is not in the list!
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D6")));
	}
	
	@Test
	public void testWhenRookOnC5PlusPiece() throws Exception{
		IPiece rook = new Rook(gf, army);		
		
		chessco.setA1Notation("C5");
		when(chessco.getRow()).thenReturn(2);
		when(chessco.getCol()).thenReturn(3);
		when(chessco.getA1Notation()).thenReturn("C5");
		when(gf.getPositionOfPiece(rook)).thenReturn(chessco);	
		
		gf.setPieceAtPosition(rook, "C5");
		
		//put a piece on the board. we assume it is of the opposite army!
		IPiece pawn = mock(IPiece.class);
		//mock object is beter te gebruiken!!
		gf.setPieceAtPosition(pawn, "F5");
		when(gf.getPieceAt("F5")).thenReturn(pawn);
		when(pawn.getColor()).thenReturn("Zwart");
		
		Assert.assertNotNull("List of possible moves may not be null", rook.getPossibleMoves());
		
		Assert.assertFalse("List must contain more possible moves", rook.getPossibleMoves().isEmpty());
		
		List<ChessboardCoordinate> list = rook.getPossibleMoves();
		
		// Fields that should be in the list of possible moves
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "C2")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "C3")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "C1")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "C7")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "C6")));

		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "A5")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "B5")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "D5")));
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "E5")));
		
		Assert.assertTrue(list.contains(new ChessboardCoordinate(board, "F5")));
		
		// proximate fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B7")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B6")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A6")));
		
		// fields from the other piece on, should not be in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"G5")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"H5")));
		
		// random fields to check they are not in the list
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A2")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"B1")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F4")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"F8")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"A5")));
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"G7")));
		
		// check that current Position of the piece is not in the list!
		Assert.assertFalse("May not be included int possMoves", list.contains(new ChessboardCoordinate(board,"D6")));
	}
}
